package com.css.dzj.zfjg.modules.clue.service.impl;

import com.alibaba.fastjson.JSON;
import com.css.dzj.zfjg.common.util.R;
import com.css.dzj.zfjg.common.util.ServiceUtil;
import com.css.dzj.zfjg.common.util.excel.ExcelUtil;
import com.css.dzj.zfjg.modules.clue.mapper.ClueMapper;
import com.css.dzj.zfjg.modules.clue.entity.Clue;
import com.css.dzj.zfjg.modules.clue.entity.QClue;
import com.css.dzj.zfjg.modules.clue.service.ClueService;
import com.css.dzj.zfjg.modules.clue.vo.ClueVerifyBuilder;
import com.css.dzj.zfjg.modules.detail.entity.CreditPushInfo;
import com.css.dzj.zfjg.sys.user.entity.LoginUser;
import com.github.stupdit1t.excel.ExcelUtils;
import com.github.stupdit1t.excel.common.ImportRspInfo;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.SneakyThrows;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * 信用线索企业详情serviceImpl
 */
@Service
public class ClueServiceImpl implements ClueService {

    @Autowired
    private ClueMapper clueMapper;

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Autowired
    private ServiceUtil serviceUtil;


    /**
     * 添加信用线索企业详情
     *
     * @param clue
     */
    @Transactional
    @Override
    public void add(Clue clue, HttpServletRequest request) {
        try {
            R r = serviceUtil.getUserInfoByRequest(request);
            if (r.getCode().equals("200")) {
                LoginUser userInfo = (LoginUser) r.get("data");
                clue.setCreateUser(userInfo.getLoginName());
            }
            clue.setCreateTime(new Date());
            clueMapper.save(clue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改信用线索企业详情
     *
     * @param clue
     */
    @Transactional
    @Override
    public void update(Clue clue) {

    }

    /**
     * 通过id查找信用线索企业详情
     *
     * @param id
     * @return
     */
    @Override
    public Clue findById(String id) {
        return clueMapper.findById(id).get();
    }


    /**
     * 分页查询所有信用线索企业详情
     *
     * @return
     */
    @Override
    public QueryResults<Clue> queryAll(Pageable pageable) {
        QClue qClue = QClue.clue;
        QueryResults<Clue> clueQueryResults = jpaQueryFactory.selectFrom(qClue)
                .orderBy(qClue.createTime.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();
        return clueQueryResults;
    }

    /**
     * 多条件分页查询信用线索企业详情
     *
     * @param pageable
     * @param enterpriseName
     * @param enterpriseIdNumber
     * @param creditClueReasons
     * @param status
     * @return
     */
    @Override
    public QueryResults<Clue> listClue(Pageable pageable, String enterpriseName, String enterpriseIdNumber, String creditClueReasons, String status) {
        QClue qClue = QClue.clue;
        Predicate predicate = qClue.isNotNull().or(qClue.isNull());
        predicate = (enterpriseName == null || enterpriseName.isEmpty()) ? predicate : ExpressionUtils.and(predicate, qClue.enterpriseName.like("%" + enterpriseName.trim() + "%"));
        predicate = (enterpriseIdNumber == null || enterpriseIdNumber.isEmpty()) ? predicate : ExpressionUtils.and(predicate, qClue.enterpriseIdNumber.like("%" + enterpriseIdNumber.trim() + "%"));
        predicate = (creditClueReasons == null || creditClueReasons.isEmpty()) ? predicate : ExpressionUtils.and(predicate, qClue.creditClueReasons.eq(creditClueReasons));
        predicate = (status == null || status.isEmpty()) ? predicate : ExpressionUtils.and(predicate, qClue.status.eq(status));
        QueryResults<Clue> clueQueryResults = jpaQueryFactory.selectFrom(qClue)
                .where(predicate)
                .orderBy(qClue.createTime.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();
        return clueQueryResults;
    }


    /**
     * 通过企业证件号码查询企业信用线索
     *
     * @param enterpriseIdNumber
     * @return
     */
    @Override
    public Clue queryByIdNumber(String enterpriseIdNumber) {
        QClue qClue = QClue.clue;
        return jpaQueryFactory.selectFrom(qClue)
                .where(qClue.enterpriseIdNumber.eq(enterpriseIdNumber))
                .fetchOne();
    }


    /**
     * 物理删除企业信用线索
     *
     * @param clue
     */
    @Override
    public void delete(Clue clue) {
        try {
            clueMapper.delete(clue);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 待定：另外一种导入
     *
     * @param file
     * @param request
     * @throws IOException
     */
    public void addClueFromExcel2(MultipartFile file, HttpServletRequest request) throws IOException {
        InputStream is = file.getInputStream();
        Workbook wb = null;
        try {
            wb = WorkbookFactory.create(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert wb != null;
        Sheet sheet = wb.getSheetAt(0);
        // 3.生成VO数据
        //参数：1.生成VO的class类型;2.校验规则;3.导入的sheet;3.从第几行导入;4.尾部非数据行数量;5.导入每条数据的回调
        ImportRspInfo<ClueVerifyBuilder> list = ExcelUtils.parseSheet(ClueVerifyBuilder.class, ClueVerifyBuilder.getInstance(), sheet, 1, 0);
        if (list.isSuccess()) {
            // 导入没有错误，打印数据
            System.out.println(JSON.toJSONString(list.getData()));
        } else {
            // 导入有错误，打印输出错误
            System.out.println(list.getMessage());
        }
    }

    @Transactional
    @Override
    public void addClueFromExcel(MultipartFile file, HttpServletRequest request) throws IOException {
        //获取原始文件名
        String originalFilename = file.getOriginalFilename();
        //文件类型
        assert originalFilename != null;
        String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //读取行数第一行开始
        Integer startRows = 1;
        InputStream is = file.getInputStream();
        // Excel导入导出的单元类
        List<String[]> strings = ExcelUtil.readData(fileType, startRows, true, is);
        // Excel行数据重复
        String message = this.lineRepeat(strings);
        if (message != null) {
            throw new RuntimeException("企业证件号码:" + message + "行重复!");
        }
        for (String[] string : strings) {
            // 企业证件号码重复时，覆盖原有数据
            if (isRepeatByEnterpriseIdNumber(string[1])) {
                Clue clue = queryByenterpriseIdNumber(string[1]);
                updClue(clue, string);
                continue;
            }
            // 将字符串数组数据转换为Clue实体,并且向数据库添加实体数据
            Clue clue = castClue(string);
            // 导入数据的信用状态为已接收
            clue.setStatus("0");
            add(clue, request);
        }
    }

    private String lineRepeat(List<String[]> strings) {
        HashSet<String> set = new HashSet<>();
        for (String[] s : strings) {
            // s[1]为：企业证件号码
            String message = s[1];
            if (set.contains(message)) {
                return message;
            }
            set.add(message);
        }
        return null;
    }

    /**
     * 判断企业证件号码重复
     *
     * @param enterpriseIdNumber
     * @return
     */
    public boolean isRepeatByEnterpriseIdNumber(String enterpriseIdNumber) {
        QClue q = QClue.clue;
        return jpaQueryFactory.selectFrom(q)
                .where(q.enterpriseIdNumber.eq(enterpriseIdNumber))
                .fetchCount() > 0;
    }

    /**
     * 企业信用线索批量反馈
     * @param file
     * @param request
     */
    @Override
    public void importToRemote(MultipartFile file, HttpServletRequest request) throws Exception {
        //获取原始文件名
        String originalFilename = file.getOriginalFilename();
        //文件类型
        assert originalFilename != null;
        String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //读取行数第一行开始
        Integer startRows = 1;
        InputStream is = file.getInputStream();
        // Excel导入导出的单元类
        List<String[]> strings = ExcelUtil.readData(fileType, startRows, true, is);
        // Excel行数据重复
        String message = this.lineRepeat(strings);
        if (message != null) {
            throw new RuntimeException("企业证件号码:" + message + "行重复!");
        }
        for (String[] string : strings) {
            // 将字符串数组数据转换为Clue实体
//            Clue clue = castClue(string);
//            add(clue, request);
            CreditPushInfo creditPushInfo = new CreditPushInfo();
            creditPushInfo.setEnterpriseIdNumber(string[1]);
            creditPushInfo.setFeedbackOrg(ServiceUtil.getOrgName(request));
            creditPushInfo.setFeedbackPerson(ServiceUtil.getLoginName(request));
            creditPushInfo.setFeedbackTime(new Date());

        }
    }

    /**
     * 转换实体
     *
     * @param s
     * @return
     */
    private Clue castClue(String[] s) {
        Clue clue = new Clue();
        /**
         * 设置excel表格对应的必填字段
         */
        try {
            clue.setEnterpriseName(s[0]); //企业名称
            clue.setEnterpriseIdNumber(s[1]); //企业证件号码
            clue.setEnterpriseIdType(s[2]); //企业证件类型
            clue.setCreditClueReasons(s[3]); //信用线索原因
            clue.setNegativeDetails(s[4]); //涉及负面详情
            //省市县级
            clue.setProvincial(s[5]);
            clue.setMunicipalLevel(s[6]);
            clue.setCountyLevel(s[7]);
            // 国标一~四级行业名称
            clue.setNationalStandard1Name(s[8]);
            clue.setNationalStandard2Name(s[9]);
            clue.setNationalStandard3Name(s[10]);
            clue.setNationalStandard4Name(s[11]);
            clue.setEvaluationDate(DateUtil.parseYYYYMMDDDate(s[12])); //评估日期
//            clue.setStatus(chinseseToNumber(s[13])); //信用评估状态
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("日期格式应符合YYYY/MM/DD或者YYYY-MM-DD格式！");
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new RuntimeException("表中缺少一列或多列！");
        }
        return clue;
    }

    /**
     * 覆盖原有Clue数据
     *
     * @param clue
     * @param s
     */
    private void updClue(Clue clue, String[] s) {
        /**
         * 设置excel表格对应的必填字段
         */
        try {
            clue.setEnterpriseName(s[0]); //企业名称
            //clue.setEnterpriseIdNumber(s[1]); //企业证件号码
            clue.setEnterpriseIdType(s[2]); //企业证件类型
            clue.setCreditClueReasons(s[3]); //信用线索原因
            clue.setNegativeDetails(s[4]); //涉及负面详情
            //省市县级
            clue.setProvincial(s[5]);
            clue.setMunicipalLevel(s[6]);
            clue.setCountyLevel(s[7]);
            // 国标一~四级行业名称
            clue.setNationalStandard1Name(s[8]);
            clue.setNationalStandard2Name(s[9]);
            clue.setNationalStandard3Name(s[10]);
            clue.setNationalStandard4Name(s[11]);
            clue.setEvaluationDate(DateUtil.parseYYYYMMDDDate(s[12])); //评估日期
            clue.setStatus("0"); //信用评估状态为已接收
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("日期格式应符合YYYY/MM/DD或者YYYY-MM-DD格式！");
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new RuntimeException("表中缺少一列或多列！");
        }
        update(clue);
    }

    /**
     * 汉字转换为数字
     *
     * @param num
     * @return
     */
    private String chinseseToNumber(String num) {
        // 信用评估状态 0:已接收 1:已调整 2：已反馈
        if ("已接收".equals(num)) {
            num = "0";
        } else if ("已调整".equals(num)) {
            num = "1";
        } else if ("已反馈".equals(num)) {
            num = "2";
        }
        return num;
    }


    /**
     * 查询全部
     *
     * @return
     */
    @Override
    public List<Map> getAll() {
        return clueMapper.getAll();
    }

    @Override
    public Clue queryByenterpriseIdNumber(String enterpriseIdNumber) {
        QClue q = QClue.clue;
        return jpaQueryFactory.selectFrom(q).where(q.enterpriseIdNumber.eq(enterpriseIdNumber)).fetchOne();
    }

}
